package com.wva.ffmpeg.utils;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.util.function.Consumer;

/**
 * @Author: hong
 * @Date: 2025/2/18 13:45:26
 */
public class FfmpegUtils {
    /**
     * 处理每一帧然后输出处理后的视频
     * @param inputVideoOptions
     * @param outputVideoOptions
     * @param frameHandlerOptions
     * @return 处理后的视频信息
     * @throws Exception
     */
    public static VideoInfo transform(
            InputVideoOptions inputVideoOptions,
            OutputVideoOptions outputVideoOptions,
            FrameHandlerOptions frameHandlerOptions
    ) throws Exception {
        if (inputVideoOptions == null)
            throw new IllegalArgumentException("输入视频参数为空");
        if (outputVideoOptions == null)
            throw new IllegalArgumentException("输出视频参数为空");

        //初始化输入流
        try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideoOptions.getFilename())) {
            //开启输入流，如果需要读取原始视频信息那么一定要先开启输入流
            grabber.start();

            //输出信息
            VideoInfo.VideoInfoBuilder videoInfoBuilder = VideoInfo.builder();

            //视频输出配置
            if (outputVideoOptions.getAudioChannel() <= 0) outputVideoOptions.setAudioChannel(grabber.getAudioChannels());
            if (outputVideoOptions.getVideoCodec() <= 0) outputVideoOptions.setVideoCodec(grabber.getVideoCodec());
            if (outputVideoOptions.getAudioCodec() <= 0) outputVideoOptions.setAudioCodec(grabber.getAudioCodec());

            Definition definition = outputVideoOptions.getDefinition();
            videoInfoBuilder.duration(grabber.getLengthInTime() / 1000000.00);
            int imageWidth = definition != null ? definition.getImageWidth() : grabber.getImageWidth();
            int imageHeight = definition != null ? definition.getImageHeight() : grabber.getImageHeight();
            videoInfoBuilder.imageWidth(imageWidth);
            videoInfoBuilder.imageHeight(imageHeight);
            videoInfoBuilder.definition(outputVideoOptions.getDefinition());

            //初始化输出流
            try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(
                    outputVideoOptions.getFilename(),
                    imageWidth,
                    imageHeight,
                    outputVideoOptions.getAudioChannel()
            )) {
                //设定输出视频和音频的编码
                recorder.setVideoCodec(outputVideoOptions.getVideoCodec());
                recorder.setAudioCodec(outputVideoOptions.getAudioCodec());

                // av_register_in_all();
                // avcodec_register_all();

                //开启输出流
                recorder.start();

                boolean hasImage = false;
                //循环处理每一帧
                if (frameHandlerOptions == null)
                    frameHandlerOptions = FrameHandlerOptions.builder().build();
                boolean first = false;
                boolean last = false;
                Consumer<Frame> firstHandler = frameHandlerOptions.getFirst();
                Consumer<Frame> everyHandler = frameHandlerOptions.getEvery();
                Consumer<Frame> lastHandler = frameHandlerOptions.getLast();
                while(true) {
                    Frame frame = grabber.grab();
                    if (frame == null) break;
                    if (!hasImage) hasImage = frame.image != null && frame.image.length > 0;
                    if (hasImage) {
                        if (firstHandler != null && !first) {
                            firstHandler.accept(frame);
                            first = true;
                        }
                        if (everyHandler != null) everyHandler.accept(frame);
                        if (lastHandler != null && !last) {
                            lastHandler.accept(frame);
                            last = true;
                        }
                    }
                    recorder.record(frame);
                }
            }
            return videoInfoBuilder.build();
        }
    }





    // /**
    //  * 从grabber读取视频信息
    //  * @param grabber
    //  * @return
    //  */
    // public static VideoInfo getVideoInfo(FFmpegFrameGrabber grabber) {
    //     VideoInfo info = new VideoInfo();
    //     int lengthInFrames = grabber.getLengthInVideoFrames();
    //     double frameRate = grabber.getVideoFrameRate();
    //     double duration = grabber.getLengthInTime() / 1000000.00;
    //     int width = grabber.getImageWidth();
    //     int height = grabber.getImageHeight();
    //     int audioChannel = grabber.getAudioChannels();
    //     // String videoCode = grabber.getVideoCodecName();
    //     // String audioCode = grabber.getAudioCodecName();
    //     int sampleRate = grabber.getSampleRate();
    //
    //     info.setLengthInFrames(lengthInFrames);
    //     info.setFrameRate(frameRate);
    //     info.setDuration(duration);
    //     info.setImageWidth(width);
    //     info.setImageHeight(height);
    //     info.setAudioChannel(audioChannel);
    //     // info.setVideoCodec(videoCode);
    //     // info.setAudioCodec(audioCode);
    //     info.setSampleRate(sampleRate);
    //     return info;
    // }
}
